package org.functional.demo;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author Zhang Yu
 * @description: TODO
 * @date 2024/5/14 15:29
 */
public class CreateStreamDemo {
    public static void main(String[] args) {
//        test1();
//        test2();
//        test3();
//        test4();
//        test5();
//        test6();
//        test7();
//        test8();
//        test9();
//        test10();
//        test11();
//        test12();
//        test13();
//        test14();
//        test15();
        test16();

    }

    /**
     * 并行
     */
    static void test16() {
        List<String> stringList = Arrays.asList("a", "c", "d", "b");
        List<String> stringList1 = Arrays.asList("A", "C", "D", "B");
        stringList.stream().parallel().sorted().forEachOrdered(System.out::println);
        stringList1.stream().parallel().sorted().forEachOrdered(System.out::println);
    }

    /**
     * 合并
     */
    static void test15() {
        Stream<List<Integer>> listStream = Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), Arrays.asList(7, 8, 9));
        listStream.flatMap(list->list.stream()).forEach(System.out::println);
    }

    /**
     * 合并
     */
    static void test14() {

        Stream<String> s1 = Arrays.asList("A", "B", "C").stream();
        Stream<String> s2 = Arrays.asList("D", "E").stream();

        Stream<String> concat = Stream.concat(s1, s2);
        concat.forEach(System.out::println);

    }

    /**
     * 跳过截取
     */
    static void test13() {
        Arrays.asList("A", "B", "C", "D", "E", "F")
                .stream()
                .skip(2)  //跳过A，B
                .limit(3)  //截取 C D E
                .forEach(System.out::println);
    }

    /**
     * 去重
     */
    static void test12() {
        Arrays.asList("A", "B", "A", "C", "B", "D").stream().distinct().forEach(System.out::println);
    }

    /**
     * 排序1
     */
    static void test11(){
        List<String> stringList = Arrays.asList("Orange", "apple", "Banana");
//        stringList.stream().sorted(String::compareToIgnoreCase).collect(Collectors.toList()).forEach(System.out::println);
        stringList.stream().sorted(String::compareToIgnoreCase).forEach(System.out::println);
    }

    /**
     * 排序
     */
    static void test10(){
        List<String> stringList = Arrays.asList("Orange", "apple", "Banana");
        stringList.stream().sorted().collect(Collectors.toList()).forEach(System.out::println);
    }

    /**
     * 按组输出2
     */
    static void test9() {
        Student student = new Student(1, "张三");
        Student student1 = new Student(1, "李四");
        Student student2 = new Student(2, "王老五");
        Student student3 = new Student(2, "李老六");
        List<Student> students = Arrays.asList(student, student1, student2, student3);
        Map<Integer, List<Student>> collect = students.stream().collect(Collectors.groupingBy(studentTmp -> studentTmp.classId, Collectors.toList()));
        System.out.println("collect = " + collect);
    }

    /**
     * 按组输出
     */
    static void test8() {
        List<String> stringList = Arrays.asList("Apple", "Banana", "Blackberry", "Coconut", "Avocado", "Cherry", "Apricots");
        Map<String, List<String>> collect = stringList.stream().collect(Collectors.groupingBy(s -> s.substring(0, 1), Collectors.toList()));
        System.out.println("collect = " + collect);
    }

    /**
     * 创建stream方法1
     */
    static void test1(){
        Stream<String> stream = Stream.of("A", "B", "C", "D");
        stream.forEach(System.out::println);
    }
    /**
     * 创建stream方法2,3
     */
    static void test2(){
        Stream<String> stream1 = Arrays.stream(new String[]{"A", "B", "C", "D"});
        Stream<String> stream2 = Arrays.asList("X", "Y", "Z").stream();
        stream1.forEach(System.out::println);
        stream2.forEach(System.out::println);
    }

    /**
     * 创建stream方法4 + stream map
     */
    static void test3(){
        Stream<Long> s1 = Stream.generate(new NatualSupplier());
        Stream<Long> s2 = s1.map(n->n*n);
        Stream<Long> s3 = s2.map(n->n-1);
        System.out.println("s3 = " + s3);
    }

    /**
     * stream limit reduce
     */
    static void test4(){
        Stream<Long> s1 = Stream.generate(new NatualSupplier());
        Stream<Long> s2 = s1.map(n->n*n);
        Stream<Long> s3 = s2.map(n->n-1);
        Stream<Long> s4 = s3.limit(10);
        Long reduce = s4.reduce(0L, (acc, n) -> acc + n);
        System.out.println("reduce = " + reduce);
    }

    /**
     * stream 转 List
     */
    static void test5(){
        Stream<String> stream = Stream.of("Apple", "", null, "Pear", " ", "Orange");
        List<String> collect = stream.filter(s -> s != null && !s.isEmpty() && s.trim().length()>0).collect(Collectors.toList());
        System.out.println("collect = " + collect);
    }

    /**
     * stream 转 数组
     */
    static void test6() {
        List<String> stringList = Arrays.asList("Apple", "Banana", "Orange");
        String[] array = stringList.stream().toArray(String[]::new);
        System.out.println("array = " + String.join(",", array));
    }

    /**
     * stream 转 map
     */
    static void test7(){
        Stream<String> stream = Stream.of("APPL:Apple", "MSFT:Microsoft");
        Map<String, String> map = stream.collect(Collectors.toMap(
                s->s.substring(0, s.indexOf(":")),
                s->s.substring(s.indexOf(":") + 1)
        ));
        System.out.println("map = " + map);
    }

}

/**
 * 自定义Supplier用于创建stream
 */
class NatualSupplier implements Supplier<Long> {
    long n = 0;
    public Long get(){
        n++;
        return n;
    }
}

class Student {
    int gradeId; // 年级
    int classId; // 班级
    String name; // 名字
    int score; // 分数

    public Student(int classId, String name) {
        this.classId = classId;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "classId=" + classId +
                ", name='" + name + '\'' +
                '}';
    }
}
